/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/** *****************************************************************************************************
 * \file     Sent_Ip_E3.c                                                                               *
 * \brief    This file mainly implements the definition of register operation interface and parse the   *
 *           sent frame                                                                                 *
 *                                                                                                      *
 * <table>                                                                                              *
 * <tr><th>Date           <th>Version                                                                   *
 * <tr><td>2023/08/18     <td>1.0.0                                                                     *
 * </table>                                                                                             *
 *******************************************************************************************************/
/********************************************************************************************************
 *                                      Include header files                                            *
 *******************************************************************************************************/
#include "SentEtimer_Ip.h"
#include "RegHelper.h"
#include "SentEtimer_Register.h"
#include "__regs_base.h"
#include "Mcal_MemLibc.h"
#include "Sent_Fault.h"
/********************************************************************************************************
 *                                         Macro definition                                             *
 *******************************************************************************************************/
/* sent driver used clock frequency */
#define SENT_ETMR_CLOCK_FREQ 24000000UL

/********************************************************************************************************
 *                                      Static variables                                                *
 *******************************************************************************************************/
/* All of the channel is physical channel */
#define SENT_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Sent_MemMap.h"
/* sent scaler value */
static SentEtimer_CounterScaler Sent_Scaler[SENT_NUM_CHANNELS];
/* channel notification status */
static boolean SentNotificationEnable[SENT_NUM_CHANNELS];
/* clk set status */
static boolean Sent_Ip_aSetClkInfo[TIMER_MODULE_NUMBER];
/* module base address information */
/* PRQA S 1504 1 */
uint32 SENT_ETMR_BASE[TIMER_MODULE_NUMBER];
/* temporary Sent Frame data buffer */
SentEtimer_Channel SentEtimer_FrameInfo[SENT_NUM_CHANNELS];
/* HwChannel Sent Frame data buffer */
static SentEtimer_Channel gSent_Channel[SENT_NUM_CHANNELS];

#define SENT_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Sent_MemMap.h"

#define SENT_START_SEC_CONST_UNSPECIFIED
#include "Sent_MemMap.h"
/* PRQA S 1504,3408 1 */
const uint8 CRC4_Table[16] = {0, 13, 7, 10, 14, 3, 9, 4, 1, 12, 6, 11, 15, 2, 8, 5};
#define SENT_STOP_SEC_CONST_UNSPECIFIED
#include "Sent_MemMap.h"

/********************************************************************************************************
 *                                      internal fcuntion                                               *
 *******************************************************************************************************/
#define SENT_START_SEC_CODE
#include "Sent_MemMap.h"

/* PRQA S 1505 EOF */
uint8 SentEtimer_Ip_Crc4CalculateWithTable2008(uint8 initial_value, uint8 const *message, uint8 len)
{
    uint8 crc_val = initial_value;
    uint32 i = 0UL;

    for ( ; i < len; i++) {
        crc_val = CRC4_Table[crc_val] ^ message[i];
    }

    return crc_val;
}

/* PRQA S 1505 */
uint8 SentEtimer_Ip_Crc4CalculateWithTable2010(uint8 initial_value, uint8 const *message, uint8 len)
{
    uint8 crc_val = initial_value;
    uint32 i = 0UL;

    for ( ; i < len; i++) {
        crc_val = CRC4_Table[crc_val] ^ message[i];
    }

    /* PRQA S 2986 1 */
    crc_val = 0U ^ CRC4_Table[crc_val];
    return crc_val;
}
/** *****************************************************************************************************
 * \brief This function set sent hardware base address
 *
 * \verbatim
 * Syntax             : FUNC(void, SENT_CODE) SentEtimer_Ip_SetBaseAddr( void )
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : None
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : This function set sent hardware base address
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
void SentEtimer_Ip_SetBaseAddr(void)
{
    SENT_ETMR_BASE[0] = APB_ETMR1_BASE;
    SENT_ETMR_BASE[1] = APB_ETMR2_BASE;
    SENT_ETMR_BASE[2] = APB_ETMR3_BASE;
    SENT_ETMR_BASE[3] = APB_ETMR4_BASE;
}

/** *****************************************************************************************************
 * \brief This function initilize sent hardware channel
 *
 * \verbatim
 * Syntax             : FUNC(void, SENT_CODE) SentEtimer_Ip_ChannelInit
 *                      (
 *                          VAR(uint8, AUTOMATIC) ChannelId,
 *                          P2CONST(SentEtimer_ChannelConfigType, AUTOMATIC, SENT_APPL_CONST) pChannelConfig
 *                      )
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : eChannel - logic channel id
 *                      pChannelConfig - channel config
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : This function initilize sent hardware channel
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
void SentEtimer_Ip_ChannelInit(uint8 eChannel, const SentEtimer_ChannelConfigType *pChannelConfig)
{
    uint32 u32Timeout = 1000U;
    uint8 TimerModule;
    uint8 HwChannel;
    SentEtimer_FastChannelType ChnFormat;
    uint8 FifoWml;
    uint32 u32Value;

    TimerModule = (uint8)pChannelConfig->SentHwChannelConfig->u8TimerModule;
    HwChannel = (uint8)pChannelConfig->SentHwChannelConfig->u8HwChannel;
    ChnFormat = pChannelConfig->SentHwChannelConfig->eFastChannel;
    FifoWml = (uint8)pChannelConfig->SentHwChannelConfig->u8FifoWml;

    /* set timer clock and predivider */
    if (Sent_Ip_aSetClkInfo[TimerModule] == FALSE)
    {
        /* set clk info */
        uint32 Clk_Set;
        /* PRQA S 1841,4542,4543 EOF */
        Clk_Set = SENT_FV_TIM_CLK_CONFIG_DIV_NUM(0);
        /* set src clock as 24M */
        /* PRQA S 0499 EOF */
        Clk_Set |= SENT_FV_TIM_CLK_CONFIG_SRC_CLK_SEL(3UL);
        Clk_Set |= SENT_BM_TIM_CLK_CONFIG_CLK_CHANGE_UPD;
        REG_WRITE32(Clk_Set, SENT_TIM_CLK_CONFIG(TimerModule));

        do
        {
            u32Timeout--;
            /* wait for clk info effective, timeout is about 5 clock */
            u32Value = (REG_READ32(SENT_TIM_CLK_CONFIG(TimerModule)) & SENT_BM_TIM_CLK_CONFIG_CLK_CHANGE_UPD);
        } while ((0x1U == u32Value) && (0UL != u32Timeout));

        Sent_Ip_aSetClkInfo[TimerModule] = TRUE;
    }

    /* calculate the expect scaler value */
    Sent_Scaler[eChannel].u32ExpectScaler = SENT_ETMR_CLOCK_FREQ / (pChannelConfig->u32TickFrequency);
    /* set timer counter ovf value 0xffffffff */
    REG_WRITE32(0xFFFFFFFFUL, SENT_LOCAL_CNT_OVF_VAL(TimerModule, HwChannel));
    REG_RMW32(SENT_LOCAL_CNT_CFG(TimerModule, HwChannel), SENT_CNT_CFG_OVF_UPD_START_BIT, 1u, 1u);

    u32Timeout = 1000U;
    do
    {
        /* wait for timer counter overflow value updated, timeout is about 5 clock */
        u32Value = (REG_READ32(SENT_LOCAL_CNT_CFG(TimerModule,
                    HwChannel)) & (1UL << SENT_CNT_CFG_OVF_UPD_START_BIT));
        u32Timeout--;
    } while ((0x1U == u32Value) && (0UL != u32Timeout));

    /* cnt will start when the first cpt event happen */
    REG_RMW32(SENT_LOCAL_CNT_CFG(TimerModule, HwChannel), SENT_CNT_CFG_START_BY_FIRST_CPT_START_BIT, 1u,
              1u);
    /* reset the counter when the cpt0 event happen */
    REG_RMW32(SENT_LOCAL_CNT_CFG(TimerModule, HwChannel), SENT_CNT_CFG_CPT0_CLR_EN_START_BIT, 1u, 1u);
    /* enable timer counter */
    /* PRQA S 3432 1 */
    REG_WRITE32(1, SENT_LOCAL_CNT_EN(TimerModule, HwChannel));

    /* Set the triggered edge as falling edge */
    /* PRQA S 3432 1 */
    REG_RMW32(SENT_CPT_CONFIG(TimerModule, HwChannel), SENT_CPT_CONFIG_CPT0_TRIG_MODE_START_BIT, 2u, 1);
    /* set the local timer as capture counter */
    /* PRQA S 3432 1 */
    REG_RMW32(SENT_CPT_CONFIG(TimerModule, HwChannel), SENT_CPT_CONFIG_CNT_SEL_START_BIT, 2u, 2u);
    REG_RMW32(SENT_CPT_CTRL(TimerModule), SENT_CPT_CTRL_CPT_CONFIG_SET_START_BIT(HwChannel), 1u, 1u);

    /* enable channel status check */
    REG_WRITE32(0xFFFFFFFFUL, SENT_FIFO_OVR_STA_ADDR32(TimerModule));
    REG_RMW32(SENT_FIFO_OVR_STA_EN_ADDR32(TimerModule), SENT_FIFO_OVR_STA_CHN_EN(HwChannel), 1U, 1U);

    /* set water mark level value */
    uint32 Chn_Wml = REG_READ32(SENT_CHN_DMA_WML(TimerModule));
    Chn_Wml &= ~SENT_FM_DMA_WML_CHN(HwChannel);
    Chn_Wml |= SENT_FV_DMA_WML_CHN(FifoWml, HwChannel);
    REG_WRITE32(Chn_Wml, SENT_CHN_DMA_WML(TimerModule));

    uint32 Dma_Ctrl = REG_READ32(SENT_CHN_DMA_CTRL(TimerModule));
    /* PRQA S 2985,3395 2 */
    /* set dma block as capture */
    Dma_Ctrl |= SENT_FV_CHN_DMA_CTRL_CHN_SEL(1U, HwChannel);
    Dma_Ctrl |= SENT_BM_CHN_DMA_CTRL_CHN_EN(HwChannel);
    REG_WRITE32(Dma_Ctrl, SENT_CHN_DMA_CTRL(TimerModule));

    /* set channel data info */
    gSent_Channel[eChannel].FrameInfo.u8Dl = (uint8)pChannelConfig->SentHwChannelConfig->eDataBitNum;

    /* set channel format */
    gSent_Channel[eChannel].eChnFormat = ChnFormat;
    /* set channel notification */
    SentNotificationEnable[eChannel] = FALSE;
    /* The hardware glitch filter is too weak, software filter may need to be added. */
    /* Filter Func*/
    if (TRUE == pChannelConfig->SentHwChannelConfig->bFiterEnable)
    {
        /* PRQA S 2985,3432 EOF */
        u32Value = SENT_CPT_FLT_EN | SENT_CPT_FLT_BOTHEDGE_SEL |
                    SENT_CPT_FLT_NEG_BAND_WID(pChannelConfig->SentHwChannelConfig->u8FiterBandwidth) |
                    SENT_CPT_FLT_POS_BAND_WID(pChannelConfig->SentHwChannelConfig->u8FiterBandwidth) |
                    SENT_CPT_FLT_SMPL_INTVAL(pChannelConfig->SentHwChannelConfig->u8SampleInterval);
    }

    REG_WRITE32(u32Value, SENT_CPT_X0_FLT(TimerModule, HwChannel));
    /* disable correctable and uncorrectable interrupt (not fetch),cause wml > 1 is allowed */
    REG_RMW32(SENT_COR_ERR_INT_SIG_EN(TimerModule), SENT_COR_ERR_NOT_FETCH_EN_BIT(HwChannel), 1U, 0U);
    REG_RMW32(SENT_UNC_ERR_INT_SIG_EN(TimerModule), SENT_UNC_ERR_NOT_FETCH_EN_BIT(HwChannel), 1U, 0U);

}

/** *****************************************************************************************************
 * \brief This function de-initilize sent hardware channel
 *
 * \verbatim
 * Syntax             : FUNC(void, SENT_CODE) SentEtimer_Ip_ChannelDeInit
 *                      (
 *                          VAR(uint8, AUTOMATIC) ChannelId,
 *                          P2CONST(SentEtimer_ChannelConfigType, AUTOMATIC, SENT_APPL_CONST) pChannelConfig
 *                      )
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : ChannelId - logic channel id
 *                      pChannelConfig - channel config
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : This function de-initilize sent hardware channel
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
void SentEtimer_Ip_ChannelDeInit(uint8 ChannelId,const SentEtimer_ChannelConfigType *pChannelConfig)
{
    uint8 TimerModule;
    uint8 HwChannel;
    uint32 u32Value;
    uint32 u32Timeout = 1000U;

    TimerModule = (uint8)pChannelConfig->SentHwChannelConfig->u8TimerModule;
    HwChannel = (uint8)pChannelConfig->SentHwChannelConfig->u8HwChannel;

    /* Turn off dma req interrupt */
    REG_RMW32(SENT_INT_STA_EN_ADDR32(TimerModule), (uint32)(20UL + HwChannel), 1u, 0u);
    REG_RMW32(SENT_INT_SIG_EN_ADDR32(TimerModule), (uint32)(20UL + HwChannel), 1u, 0u);
    /* disable cpt module */
    REG_RMW32(SENT_CPT_CTRL(TimerModule), SENT_CPT_CTRL_CPT_EN_START_BIT(HwChannel), 1u, 0u);

    /* restore timer counter overflow value 0 */
    REG_WRITE32(0, SENT_LOCAL_CNT_OVF_VAL(TimerModule, HwChannel));
    REG_RMW32(SENT_LOCAL_CNT_CFG(TimerModule, HwChannel), SENT_CNT_CFG_OVF_UPD_START_BIT, 1u, 1u);

    do
    {
        /* wait for timer counter overflow value updated, timeout is about 5 clock */
        u32Value = (REG_READ32(SENT_LOCAL_CNT_CFG(TimerModule,
                     HwChannel)) & (1UL << SENT_CNT_CFG_OVF_UPD_START_BIT));
        SentHook_Sent_RegVal_Fix();
        u32Timeout--;
    } while ((0x1U == u32Value) && (0UL != u32Timeout));
    /* PRQA S 2985 40 */
    /* restore the cnt cfg */
    REG_RMW32(SENT_LOCAL_CNT_CFG(TimerModule, HwChannel), SENT_CNT_CFG_START_BY_FIRST_CPT_START_BIT, 1u,
              0u);
    REG_RMW32(SENT_LOCAL_CNT_CFG(TimerModule, HwChannel), SENT_CNT_CFG_CPT0_CLR_EN_START_BIT, 1u, 0u);
    /* disable timer counter */
    /* PRQA S 3432 EOF */
    REG_WRITE32(0, SENT_LOCAL_CNT_EN(TimerModule, HwChannel));

    /* Set the triggered edge as default edge */
    REG_RMW32(SENT_CPT_CONFIG(TimerModule, HwChannel), SENT_CPT_CONFIG_CPT0_TRIG_MODE_START_BIT, 2u, 0);
    /* set the local timer as default counter */
    REG_RMW32(SENT_CPT_CONFIG(TimerModule, HwChannel), SENT_CPT_CONFIG_CNT_SEL_START_BIT, 2u, 0u);
    REG_RMW32(SENT_CPT_CTRL(TimerModule), SENT_CPT_CTRL_CPT_CONFIG_SET_START_BIT(HwChannel), 1u, 1u);

    /* disable channel status check */
    REG_WRITE32(0xFFFFFFFFUL, SENT_FIFO_OVR_STA_ADDR32(TimerModule));
    REG_RMW32(SENT_FIFO_OVR_STA_EN_ADDR32(TimerModule), SENT_FIFO_OVR_STA_CHN_EN(HwChannel), 1U, 0U);

    /* restore water mark level value */
    uint32 Chn_Wml = REG_READ32(SENT_CHN_DMA_WML(TimerModule));
    Chn_Wml &= ~SENT_FM_DMA_WML_CHN(HwChannel);
    Chn_Wml |= SENT_FV_DMA_WML_CHN(0U, HwChannel);
    REG_WRITE32(Chn_Wml, SENT_CHN_DMA_WML(TimerModule));

    /* set dma block as default block  */
    /* PRQA S 3395 EOF */
    uint32 Dma_Ctrl = REG_READ32(SENT_CHN_DMA_CTRL(TimerModule));
    Dma_Ctrl |= SENT_FV_CHN_DMA_CTRL_CHN_SEL(0U, HwChannel);
    REG_WRITE32(Dma_Ctrl, SENT_CHN_DMA_CTRL(TimerModule));

    /* The hardware glitch filter is too weak, software filter may need to be added. */
    /* Filter Func*/
    REG_WRITE32(0x0, SENT_CPT_X0_FLT(TimerModule,HwChannel));

    /* restore timer clock and predivider */
    if (Sent_Ip_aSetClkInfo[TimerModule] == TRUE)
    {
        /* set clk info */
        uint32 Clk_Set;
        Clk_Set = SENT_FV_TIM_CLK_CONFIG_DIV_NUM(0);
        /* set src clock as default clock source */
        Clk_Set |= SENT_FV_TIM_CLK_CONFIG_SRC_CLK_SEL(0);
        Clk_Set |= SENT_BM_TIM_CLK_CONFIG_CLK_CHANGE_UPD;
        REG_WRITE32(Clk_Set, SENT_TIM_CLK_CONFIG(TimerModule));

        u32Timeout = 1000U;
        do {
            /* wait for clk info effective, timeout is about 5 clock */
            u32Value = (REG_READ32(SENT_TIM_CLK_CONFIG(TimerModule)) &
                        SENT_BM_TIM_CLK_CONFIG_CLK_CHANGE_UPD);
            SentHook_Sent_RegVal_Fix();
            /* PRQA S 3415,3558,3440,4558 EOF */
        } while ((0x1U == u32Value) && (u32Timeout--));
        Sent_Ip_aSetClkInfo[TimerModule] = FALSE;
    }

    /* read empty fifo data, if fifo is not empty */
    /* PRQA S 3440,4558 EOF */
    while (!((REG_READ32(SENT_FIFO_STA(TimerModule)) >> ((8u * HwChannel) + 1u)) & 0x1U))
    {
        u32Value = REG_READ32(SENT_FIFO_ADDR32(TimerModule, HwChannel));

        /* Avoid warnings */
        /* PRQA S 2982 EOF */
        u32Value++;
    }

    /* reset eTimer HwChannel*/
    REG_RMW32(SENT_RST_CHANNEL(TimerModule), HwChannel, 1u, 1u);
    u32Timeout = 1000U;
    do
    {
        /* wait for HwChannel reset finished, timeout is about 5 clock */
        u32Value = (REG_READ32(SENT_RST_CHANNEL(TimerModule)) & (0x1UL << HwChannel));
        SentHook_Sent_RegVal_Fix();
    } while ((0x1U == u32Value) && (u32Timeout--));

    /* restore sent parameter */
    Sent_Scaler[ChannelId].u32ExpectScaler = 0;
    Sent_Scaler[ChannelId].u32ActualScaler = 0;
    gSent_Channel[ChannelId].FrameInfo.u8Dl = 0;
    gSent_Channel[ChannelId].eChnFormat = SENTETIMER_STANDARD_FORMAT;
    SentNotificationEnable[ChannelId] = FALSE;
}

/** *****************************************************************************************************
 * \brief This function start recieve the sent frame
 *
 * \verbatim
 * Syntax             : FUNC(void, SENT_CODE) SentEtimer_Ip_StartReciever
 *                      (
 *                          VAR(uint8, AUTOMATIC) ChannelId,
 *                          P2CONST(SentEtimer_HwChannelConfigType, AUTOMATIC, SENT_APPL_CONST) pHwChannelConfig
 *                      )
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : ChannelId - logic channel id
 *                      pChannelConfig - channel config
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : This function start recieve the sent frame
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
void SentEtimer_Ip_StartReciever(uint8 ChannelId, const SentEtimer_HwChannelConfigType *pHwChannelConfig)
{
    uint8 TimerModule = (uint8)pHwChannelConfig->u8TimerModule;
    uint8 HwChannel = (uint8)pHwChannelConfig->u8HwChannel;
    /* Turn on dma req interrupt */
    REG_RMW32(SENT_INT_STA_EN_ADDR32(TimerModule), (uint32)(20UL + HwChannel), 1u, 1u);
    REG_RMW32(SENT_INT_SIG_EN_ADDR32(TimerModule), (uint32)(20UL + HwChannel), 1u, 1u);
    /* enable cpt module */
    REG_RMW32(SENT_CPT_CTRL(TimerModule), SENT_CPT_CTRL_CPT_EN_START_BIT(HwChannel), 1u, 1u);
    /* update the channel error status */
    gSent_Channel[ChannelId].eError = (uint32)SENTETIMER_OK;
    /* set channel initial frame state */
    gSent_Channel[ChannelId].eCurstate = SENTETIMER_IDLE;

    if (pHwChannelConfig->bNotifyFrameOver == TRUE)
    {
        SentNotificationEnable[ChannelId] = TRUE;
    }
}

/** *****************************************************************************************************
 * \brief This function stop recieve the sent frame
 *
 * \verbatim
 * Syntax             : FUNC(void, SENT_CODE) SentEtimer_Ip_StopReciever
 *                      (
 *                          VAR(uint8, AUTOMATIC) ChannelId,
 *                          P2CONST(SentEtimer_HwChannelConfigType, AUTOMATIC, SENT_APPL_CONST) pHwChannelConfig
 *                      )
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : ChannelId - logic channel id
 *                      pChannelConfig - channel config
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : This function stop recieve the sent frame
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
void SentEtimer_Ip_StopReciever(uint8 ChannelId, const SentEtimer_HwChannelConfigType *pHwChannelConfig)
{
    uint8 TimerModule = (uint8)pHwChannelConfig->u8TimerModule;
    uint8 HwChannel = (uint8)pHwChannelConfig->u8HwChannel;
    /* PRQA S 2985 8 */
    /* Turn off dma req interrupt */
    REG_RMW32(SENT_INT_STA_EN_ADDR32(TimerModule), (uint32)(20UL + HwChannel), 1u, 0u);
    REG_RMW32(SENT_INT_SIG_EN_ADDR32(TimerModule), (uint32)(20UL + HwChannel), 1u, 0u);
    /* disable cpt module */
    REG_RMW32(SENT_CPT_CTRL(TimerModule), SENT_CPT_CTRL_CPT_EN_START_BIT(HwChannel), 1u, 0u);
    /* update the channel error status */
    gSent_Channel[ChannelId].eError = (uint32)SENTETIMER_OK;
    /* set channel initial frame state */
    gSent_Channel[ChannelId].eCurstate = SENTETIMER_IDLE;
    SentNotificationEnable[ChannelId] = FALSE;
}

#define SENT_STOP_SEC_CODE
#include "Sent_MemMap.h"

#define SENT_START_SEC_CODE_FAST
#include "Sent_MemMap.h"

/** *****************************************************************************************************
 * \brief This function parse the sent frame message
 *
 * \verbatim
 * Syntax             : FUNC(void, SENT_CODE) SentEtimer_Ip_Parse_Massage
 *                      (
 *                          VAR(uint8, AUTOMATIC) ChannelId,
 *                          P2CONST(SentEtimer_HwChannelConfigType, AUTOMATIC, SENT_APPL_CONST) ChannelConfig
 *                      )
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : ChannelId - logic channel id
 *                      ChannelConfig - channel config
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : This function parse the sent frame message
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
void SentEtimer_Ip_Parse_Massage(uint8 ChannelId, const SentEtimer_ChannelConfigType *ChannelConfig)
{
    uint32 Value;
    uint8 TimerModule;
    uint8 HwChannel;
    uint32 FifoSta;
    boolean PausePulse;
    uint32 Reminder;
    uint32 i;
    uint32 fifoCorErr;
    uint32 fifoErr;
    uint8 CrcCalc;


    TimerModule = (uint8)ChannelConfig->SentHwChannelConfig->u8TimerModule;
    HwChannel = (uint8)ChannelConfig->SentHwChannelConfig->u8HwChannel;
    PausePulse = ChannelConfig->SentHwChannelConfig->bPausePulse;
    fifoCorErr = REG_READ32(SENT_FIFO_OVR_STA_ADDR32(TimerModule));
    /*fifo err status check */
    fifoErr = fifoCorErr & ((uint32)(0x1UL << SENT_FIFO_OVR_STA_CHN_EN(HwChannel)));

    /* read empty fifo data and clear frame current status, if fifo overflow */
    if (0x0UL < fifoErr)
    {
        while (!((REG_READ32(SENT_FIFO_STA(TimerModule)) >> ((8u * HwChannel) + 1u)) & 0x1U))
        {
            uint32 u32Value = REG_READ32(SENT_FIFO_ADDR32(TimerModule, HwChannel));

            /* Avoid warnings */
            /* PRQA S 2982 EOF */
            u32Value++;
        }
        /* clear fifo err status */
        REG_RMW32(SENT_FIFO_OVR_STA_ADDR32(TimerModule), SENT_FIFO_OVR_STA_CHN_EN(HwChannel), 1U, 1U);
        gSent_Channel[ChannelId].eCurstate = SENTETIMER_IDLE;
        gSent_Channel[ChannelId].FrameInfo.u8RxIndex = 0;
    }
    else
    {
        FifoSta = REG_READ32(SENT_FIFO_STA(TimerModule));

        /* read fifo value */
        for (i = 0; i < ((FifoSta >> ((8u * HwChannel) + 2u)) & 0x1fu); i++)
        {
            Value = REG_READ32(SENT_FIFO_ADDR32(TimerModule, HwChannel));

            switch (gSent_Channel[ChannelId].eCurstate)
            {
            case SENTETIMER_IDLE:
            {
                /* Verification frequency valid */
                uint32 Scaler = Value / 56U;
                uint32 ErrRange = (Scaler * 10U) / (Sent_Scaler[ChannelId].u32ExpectScaler);
                gSent_Channel[ChannelId].eError = (uint32)SENTETIMER_OK;

                if ((ErrRange >= 8U) && (ErrRange <= 12U))
                {
                    Sent_Scaler[ChannelId].u32ActualScaler = Scaler;
                    gSent_Channel[ChannelId].eCurstate = SENTETIMER_SYNC;
                }
                else
                {
                    /* PRQA S 4432 2 */
                    gSent_Channel[ChannelId].eError |= (uint32)SENTETIMER_SYNC_ERR;
                    gSent_Channel[ChannelId].eError |= (uint32)SENTETIMER_TICK_FREQ_ERR;
                }

                break;
            }

            case SENTETIMER_SYNC:
            {
                uint32 StatusTick = (Value * 10U) / (Sent_Scaler[ChannelId].u32ActualScaler);
                Reminder = StatusTick % 100U;
                Reminder = Reminder % 10U;
                /* PRQA S 1842,3226 EOF */
                (Reminder < 5) ? (StatusTick = StatusTick / 10U) : (StatusTick = (StatusTick / 10U) + 1U);

                /* Verification tick number */
                if ((StatusTick < 12U) || (StatusTick > 27U))
                {
                    gSent_Channel[ChannelId].eError |= (uint32)SENTETIMER_STATUS_ERR;
                }

                /* status value */
                gSent_Channel[ChannelId].FrameInfo.u8Status = (uint8)(StatusTick - 12U);
                gSent_Channel[ChannelId].FrameInfo.u8RxIndex = 0;
                gSent_Channel[ChannelId].eCurstate = SENTETIMER_DATA;
                break;
            }

            case SENTETIMER_DATA:
            {
                uint32 DataTick = (Value * 10U) / (Sent_Scaler[ChannelId].u32ActualScaler);
                Reminder = DataTick % 100U;
                Reminder = Reminder % 10U;
                /* PRQA S 1842,3226,1840 EOF */
                (Reminder < 5) ? (DataTick = DataTick / 10U) : (DataTick = (DataTick / 10U) + 1);
                uint8 RxIdx = gSent_Channel[ChannelId].FrameInfo.u8RxIndex;

                if ((DataTick < 12U) || (DataTick > 27U))
                {
                    /* PRQA S 4432 1 */
                    gSent_Channel[ChannelId].eError |= (uint32)SENTETIMER_DATA_ERR;
                }

                /* Data Value */
                gSent_Channel[ChannelId].FrameInfo.u8Rxframe[RxIdx] = (uint8)(DataTick - 12U);
                gSent_Channel[ChannelId].FrameInfo.u8RxIndex += 1U;

                if (gSent_Channel[ChannelId].FrameInfo.u8RxIndex == gSent_Channel[ChannelId].FrameInfo.u8Dl)
                {
                    gSent_Channel[ChannelId].FrameInfo.u8RxIndex = 0;
                    gSent_Channel[ChannelId].eCurstate = SENTETIMER_CRC;
                }

                break;
            }

            case SENTETIMER_CRC:
            {
                uint32 CrcTick = (Value * 10U) / (Sent_Scaler[ChannelId].u32ActualScaler);
                Reminder = CrcTick % 100U;
                Reminder = Reminder % 10U;
                (Reminder < 5U) ? (CrcTick = CrcTick / 10U) : (CrcTick = (CrcTick / 10U) + 1U);

                if ((CrcTick < 12U) || (CrcTick > 27U))
                {
                    /* PRQA S 4432 1 */
                    gSent_Channel[ChannelId].eError |= (uint32)SENTETIMER_CRC_ERR;
                }

                uint8 DataLength = gSent_Channel[ChannelId].FrameInfo.u8Dl;
                if (SENTETIMER_SAE_J2716_2008 == ChannelConfig->SentHwChannelConfig->crc4Select)
                {
                    CrcCalc =  SentEtimer_Ip_Crc4CalculateWithTable2008(5, gSent_Channel[ChannelId].FrameInfo.u8Rxframe,
                                                                                        DataLength);
                }
                else
                {
                    CrcCalc =  SentEtimer_Ip_Crc4CalculateWithTable2010(5, gSent_Channel[ChannelId].FrameInfo.u8Rxframe,
                                                                                        DataLength);
                }

                /* PRQA S 1840 EOF */
                if (CrcCalc != (CrcTick - 12))
                {
                    /* PRQA S 4432 1 */
                    gSent_Channel[ChannelId].eError |= (uint32)SENTETIMER_CRC_ERR;
                }

                /* saved crc value */
                gSent_Channel[ChannelId].FrameInfo.u8Crc = (uint8)(CrcTick - 12U);

                /* update current frame newest status */
                /* PRQA S 0315,3200 EOF */
                Mcal_MemCpy(&SentEtimer_FrameInfo[ChannelId], &gSent_Channel[ChannelId], sizeof(SentEtimer_Channel));
                SentEtimer_FrameInfo[ChannelId].bReadFlag = TRUE;

                /* callback user function */
                if (PausePulse == TRUE)
                {
                    gSent_Channel[ChannelId].eCurstate = SENTETIMER_PAUSE;
                }
                else
                {
                    gSent_Channel[ChannelId].eCurstate = SENTETIMER_IDLE;

                    if (SentNotificationEnable[ChannelId] == TRUE)
                    {
                        ChannelConfig->SentHwChannelConfig->pfFrameOverNotification();
                    }
                }
                break;
            }

            case SENTETIMER_PAUSE:
            {
                gSent_Channel[ChannelId].eCurstate = SENTETIMER_IDLE;

                if (SentNotificationEnable[ChannelId] == TRUE)
                {
                    ChannelConfig->SentHwChannelConfig->pfFrameOverNotification();
                }

                break;
            }
            /* PRQA S 2016 1 */
            default:
            {
                break;
            }
            }
        }
    }
}

/** *****************************************************************************************************
 * \brief This function get the interrupt status
 *
 * \verbatim
 * Syntax             : FUNC(uint32, SENT_CODE) SentEtimer_Ip_GetInterrupt
 *                          (
 *                              VAR(uint8, AUTOMATIC) eModule
 *                          )
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : eModule - etimer hardware module
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : the interrupt status
 *
 * Description        : This function get the interrupt status
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
uint32 SentEtimer_Ip_GetInterrupt(uint8 eModule)
{
    return REG_READ32(SENT_INT_STA_ADDR32(eModule));
}

/** *****************************************************************************************************
 * \brief This function get the interrupt status
 *
 * \verbatim
 * Syntax             : FUNC(uint32, SENT_CODE) SentEtimer_Ip_ClearInterrupt
 *                          (
 *                              VAR(uint8, AUTOMATIC) eModule
 *                              VAR(uint8, AUTOMATIC) Position
 *                          )
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : eModule - etimer hardware module
 *                      Position - clear bit position
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : This function clear the interrupt status
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
void SentEtimer_Ip_ClearInterrupt(uint8 eModule, uint8 Position)
{
    REG_WRITE32( 1UL << Position, SENT_INT_STA_ADDR32(eModule));
}

#define SENT_STOP_SEC_CODE_FAST
#include "Sent_MemMap.h"
